package com.myk.game.gobangchess.ai.startzone;

import java.util.Arrays;

public class ColorSetting {

    public static int[] colorSetting(int[] topFitnessesSorted, int[][] topGenesSorted,
                                     int[] topFitnessesSortedAlt, int[][] topGenesSortedAlt,
                                     int[][] baseBoard, int remainNum, int remainWhiteNum, int targetColor) {
        int[] settingIdx1 = {0, 0};
        int[] settingIdx2 = {0, 0};

        int lengthTopFitnessesSorted = topFitnessesSorted.length;
        int[] topGenesSum = sumColumns(topGenesSorted);
        int topGenesNum = lengthTopFitnessesSorted;
        double[] topGenesMean = divideArray(topGenesSum, topGenesNum);

        int lengthTopFitnessesSortedAlt = topFitnessesSortedAlt.length;
        double[] topGenesMeanAlt;
        if (lengthTopFitnessesSortedAlt > 0) {
            int[] topGenesSumAlt = sumColumns(topGenesSortedAlt);
            int topGenesNumAlt = lengthTopFitnessesSortedAlt;
            topGenesMeanAlt = divideArray(topGenesSumAlt, topGenesNumAlt);
        } else {
            topGenesMeanAlt = new double[topGenesSorted[0].length];
        }

        boolean[] rowsContainsTarget = new boolean[9];
        boolean[] colsContainsTarget = new boolean[9];

        for (int i = 0; i < 9; i++) {
            rowsContainsTarget[i] = containsTarget(baseBoard[i], targetColor);
        }

        for (int j = 0; j < 9; j++) {
            colsContainsTarget[j] = containsTargetInColumn(baseBoard, j, targetColor);
        }

        int sumRows = sumBoolean(rowsContainsTarget);
        int sumCols = sumBoolean(colsContainsTarget);

        int[] rowZerosCount = countZerosRowWise(baseBoard);
        int[] colZerosCount = countZerosColumnWise(baseBoard);

        int n = 0; 
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (baseBoard[i][j] == 0) {
                    if (!rowsContainsTarget[i] && sumRows < 8) {
                        topGenesMean[n] *= (1 + 1.0 / (rowZerosCount[i]));
                    }
                    if (!colsContainsTarget[j] && sumCols < 8) {
                        topGenesMean[n] *= (1 + 1.0 / (colZerosCount[j]));
                    }
                    n++;
                }
            }
        }

        double[] topGenesMeanAdd = new double[topGenesMean.length];
        double[] topGenesMeanMinus = new double[topGenesMean.length];
        for (int i = 0; i < topGenesMean.length; i++) {
            topGenesMeanAdd[i] = topGenesMean[i] * (1 + 0.3 * topGenesMeanAlt[i]);
            topGenesMeanMinus[i] = topGenesMeanAlt[i] - topGenesMean[i];
        }

        int maxIdxAdd = maxIndex(topGenesMeanAdd);
        n = 0;
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (baseBoard[i][j] == 0) {
                    if (n == maxIdxAdd) {
                        settingIdx1[0] = i + 1; 
                        settingIdx1[1] = j + 1; 
                    }
                    n++;
                }
            }
        }

        topGenesMeanMinus[maxIdxAdd] = -1;
        if(targetColor == -1){
            remainNum -= 1;
        }
        double thresholdWhite = remainNum <= remainWhiteNum ? 0.33 : 0.78;
        if(remainNum>=10){
            thresholdWhite = thresholdWhite+0.15;
        }

        if (remainWhiteNum > 0 && lengthTopFitnessesSortedAlt > 0) {
            int maxIdxMinus = maxIndex(topGenesMeanMinus);
            if (topGenesMeanMinus[maxIdxMinus] >= thresholdWhite) {
                n = 0;
                for (int i = 0; i < 9; i++) {
                    for (int j = 0; j < 9; j++) {
                        if (baseBoard[i][j] == 0) {
                            if (n == maxIdxMinus) {
                                settingIdx2[0] = i + 1; 
                                settingIdx2[1] = j + 1; 
                            }
                            n++;
                        }
                    }
                }
            }
        }

        return new int[]{settingIdx1[0], settingIdx1[1], settingIdx2[0], settingIdx2[1]};
    }

    private static int[] sumColumns(int[][] matrix) {
        return Arrays.stream(matrix).reduce((a, b) -> {
            for (int i = 0; i < a.length; i++) {
                a[i] += b[i];
            }
            return a;
        }).orElse(new int[]{});
    }

    private static double[] divideArray(int[] array_int, int divisor_int) {
        double[] array = new double[array_int.length];
        for (int i = 0; i < array_int.length; i++) {
            array[i] = (double) array_int[i];
        }
        double divisor = Double.valueOf(divisor_int);
        return Arrays.stream(array).map(val -> val / divisor).toArray();
    }

    private static boolean containsTarget(int[] array, int target) {
        for (int value : array) {
            if (value == target) {
                return true;
            }
        }
        return false;
    }

    private static boolean containsTargetInColumn(int[][] matrix, int column, int target) {
        for (int[] row : matrix) {
            if (row[column] == target) {
                return true;
            }
        }
        return false;
    }

    private static int sumBoolean(boolean[] array) {
        int sum = 0;
        for (boolean b : array) {
            sum += b ? 1 : 0;
        }
        return sum;
    }

    private static int[] countZerosRowWise(int[][] matrix) {
        return Arrays.stream(matrix).mapToInt(row -> (int) Arrays.stream(row).filter(num -> num == 0).count()).toArray();
    }

    private static int[] countZerosColumnWise(int[][] matrix) {
        int[] count = new int[matrix[0].length];
        for (int[] row : matrix) {
            for (int j = 0; j < row.length; j++) {
                if (row[j] == 0) {
                    count[j]++;
                }
            }
        }
        return count;
    }

    private static int maxIndex(double[] array) {
        int maxIndex = 0;
        for (int i = 1; i < array.length; i++) {
            if (array[i] > array[maxIndex]) {
                maxIndex = i;
            }
        }
        return maxIndex;
    }


    public static void main(String[] args) {
        
    }
}
